/*
 * @Descripttion: 
 * @version: 
 * @Author: wtzhang
 * @Date: 2021-07-07 15:49:24
 * @LastEditors: wtzhang
 * @LastEditTime: 2021-07-07 17:06:00
 */
(function () {
  console.log('******************** 泛型 *********************');
  // function fn(a: any): any {
  //   return a;
  // }
  // 泛型：在定义函数或者类时，如果遇到类型不明确就可以使用泛型。相对于any的好处就是避免直接把类型检查跳过。
  // 一个简单的泛型
  // function fn<泛型值>(a参数: 参数类型): 返回值类型 {
  //   return a返回值;
  // }
  function fn<T>(arg: T): T {
    return arg;
  }

  // 用法：可以直接调用具有泛型的函数
  fn(10); // 像这种没有指定泛型，ts会自动对类型进行推断，但不是所有的都能推断出来
  fn<string>('hello'); // 指定泛型，指定 string 他就是string，指定number就是number，指定什么它就是什么
  fn<number>(123);
  
  // 函数中可以声明多个泛型
  function test<T, K>(a: T, b: K): K {
    return b
  }
  test<number, string>(10, 'hello')

  // 类也有泛型
  class MyClass <T>{
    name: T;
    constructor(name: T) {
      this.name = name
    }
  }
  const cc = new MyClass<string>('孙行者')

  // 泛型继承
  interface Inter {
    length: number;
  }
  // T extends Inter 表示 泛型T 必须是 Inter 实现类（子类）
  function fn3<T extends Inter>(a: T): number {
    return a.length
  }
  fn3('123') // 传的是一个字符串，字符串有length
  // fn3(123) // 传数字，数字没有length，报错如下图①
  fn3({ length: 10 }) // 没问题
  // fn3({ name: 'hello' }) // 报错，如图②
  

})()